/*
 * @Author: hanyuanjiao
 * @Date: 2025-07-23 21:20:21
 * @LastEditors: Please set LastEditors
 * @LastEditTime: 2025-08-19 11:42:01
 * @Description: 请填写简介
 */
#include "mem.h"
#include "simu8051.h"
#include <stdio.h>
#include <stdlib.h>
extern simu8051_t simu;
// 8051芯片读数据
static uint8_t read_xram(uint16_t addr)
{
    return simu.mem.xram[addr];
}
static uint8_t read_code(uint16_t addr)
{
    return simu.mem.code[addr];
}
static uint8_t read_sfr(uint8_t addr)
{
#if 1    //用于串口收发测试
    if (addr == SFR_SBUF)
    {
        return simu8051_uart_read();
    }
#endif
    switch (addr)
    {
    default:
        // sfr地址从0x80开始,但是存储在从0开始的数组sfr中
        addr -= MEM_IRAM_SIZE;
        return (addr < MEM_SFR_SIZE) ? simu.mem.sfr[addr] : 0;
    }
}
static uint8_t read_iram(uint8_t addr)
{
    if (addr >= MEM_IRAM_SIZE)
    {
        return read_sfr(addr);
    }
    else
    {
        return simu.mem.iram[addr];
    }
}
/**
 * @description: 位寻址
 * @param {uint8_t} addr属于时0x20~0x2F,[32,47],addr=[0,127],128位
 *                       0x80~0xF0,addr=0x80~0x87,0x88~8x8f,0x90~0x97,0x98~0x9f,0xa0~0xa7,...,0xf0~0xf7,[128,255],共128位
 * @return {*}
 */
static uint8_t read_bit(uint8_t addr)
{
    uint8_t bit_idx = addr % 8;
    if (addr < MEM_BIT_SFR_START)
    {
        uint8_t byte_idx = addr / 8 + MEM_BIT_IRAM_START;
        return simu.mem.iram[byte_idx] & (1 << bit_idx) ? 1 : 0;
    }
    else
    {
        //变成0,8,16,24
        uint8_t byte_idx = (addr - MEM_BIT_SFR_START) / 8 * 8;
        return simu.mem.sfr[byte_idx] & (1 << bit_idx) ? 1 : 0;
    }
}
// 8051芯片写数据
static void write_xram(uint16_t addr, uint8_t data)
{
    simu.mem.xram[addr] = data;
}
static void write_code(uint16_t addr, uint8_t data)
{
    simu.mem.code[addr] = data;
}
static void write_sfr(uint8_t addr, uint8_t data)
{
#if 1    //用于串口收发测试
    if (addr == SFR_SBUF)
    {
        simu8051_uart_write(data);
    }
#endif
    if (addr < 128 || addr > 256)
    {
        printf("write_sfr:error addr:0x%2x\n", addr);
        exit(-1);
    }
    addr -= MEM_IRAM_SIZE;
    simu.mem.sfr[addr] = data;
}
static void write_iram(uint8_t addr, uint8_t data)
{
    if (addr >= MEM_IRAM_SIZE)
    {
        write_sfr(addr, data);
    }
    else
    {
        simu.mem.iram[addr] = data;
    }
}
static void write_bit(uint8_t addr, uint8_t bit)
{
    uint8_t bit_idx = addr % 8;
    bit &= 0x01;
    // addr(0,127) -> (0x20~0x2F)
    if (addr < MEM_IRAM_SIZE)
    {
        uint8_t byte_idx = addr / 8 + MEM_BIT_IRAM_START;
        simu.mem.iram[byte_idx] &= ~(1 << bit_idx);
        simu.mem.iram[byte_idx] |= bit ? (1 << bit_idx) : 0;
    }
    else
    {
        // addr(128,255)-> (0x80 ~ 0xF0)
        //此处的addr,0x80,0x81指的是地址0x80中的第0位,第1位
        uint8_t byte_idx = (addr - MEM_BIT_SFR_START) / 8 * 8;
        simu.mem.sfr[byte_idx] &= ~(1 << bit_idx);
        simu.mem.sfr[byte_idx] |= bit ? (1 << bit_idx) : 0;
    }
}

uint8_t simu8051_read(mem_type_t type, uint16_t addr)
{
    switch (type)
    {
    case MEM_TYPE_IRAM:
        return read_iram((uint8_t)addr);
    case MEM_TYPE_XRAM:
        return read_xram(addr);
    case MEM_TYPE_CODE:
        return read_code(addr);
    case MEM_TYPE_SFR:
        return read_sfr((uint8_t)addr);
    case MEM_TYPE_BIT:
        return read_bit((uint8_t)addr);
    default:
        printf("simu8051_read unknow mem type:%d\n", type);
        return -1;
    }
}
void simu8051_write(mem_type_t type, uint16_t addr, uint8_t data)
{
    switch (type)
    {
    case MEM_TYPE_IRAM:
        write_iram((uint8_t)addr, data);
        break;
    case MEM_TYPE_XRAM:
        write_xram(addr, data);
        break;
    case MEM_TYPE_CODE:
        write_code(addr, data);
        break;
    case MEM_TYPE_SFR:
        write_sfr((uint8_t)addr, data);
        break;
    case MEM_TYPE_BIT:
        write_bit((uint8_t)addr, data);
        break;
    default:
        printf("simu8051_write unknow mem type:%d\n", type);
        break;
    }
}